gusucode.com > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序 > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序/code/Src/Client/scemflib/SCEMFDocPage.cpp
//Download by http://www.NewXing.com /* * This file is part of the EMFexplorer projet. * Copyright (C) 2004 Smith Charles. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * Extension: for commercial use, apply the Equity Public License, which * adds to the normal terms of the GLPL a condition of donation to the author. * If you are interested in support for this source code, * contact Smith Charles <smith.charles@free.fr> for more information. */ #include "stdafx.h" #include "SCEMFDocPage.h" #include "SCFileTypes.h" #include "SCEMFDoc.h" #include "SCGenInclude.h" #include SC_INC_GENLIB(SCGenDefs.h) #include SC_INC_SHARED(SCZipFile.h) #include SC_INC_ERRLIB(wErr.h) #include SC_INC_WINLIB(SCAlphaBand.h) #include "SCGdiplusUtils.h" // Page comment, credit ... #define SC_DFLT_CMT_HEIGHT (16*2) #define SC_DFLT_CRD_HEIGHT (SC_DFLT_CMT_HEIGHT/2) #define SC_DFLT_CMT_FACE _T("Times New Roman") #define SC_DFLT_CMT_FAMILY FF_ROMAN #define SC_DFLT_CMT_SIZE 18 #define SC_DFLT_CMT_STYLE SC_BAND_BOLD #define SC_DFLT_CRD_FACE SC_DFLT_CMT_FACE #define SC_DFLT_CRD_FAMILY SC_DFLT_CMT_FAMILY #define SC_DFLT_CRD_SIZE 10 #define SC_DFLT_CRD_STYLE (SC_BAND_BOLD|SC_BAND_ITALIC) //-- #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif SCEMFDocPage::SCEMFDocPage(SCEMFDoc* pParent): m_pParentDoc(pParent), m_uiType(SC_FSTATE_DELAYED|SC_FTYPE_UKN), m_hEMF(NULL), m_bDirty(FALSE), m_rectSize(0,0,0,0), m_bInflate(FALSE), m_rectInflate(0,0,0,0), m_pPgComment(NULL), m_pPgCredit(NULL) { ASSERT(m_pParentDoc); } SCEMFDocPage::~SCEMFDocPage() { SMC_DELETE(m_pPgComment); SMC_DELETE(m_pPgCredit); if (m_hEMF) ::DeleteEnhMetaFile(m_hEMF); } // Special, unsafe, stuff: Copy is not full. // Both objects hold the EMF, one must detach it before any destructor is called. void SCEMFDocPage::SCCopyFrom(const SCEMFDocPage& rDocPage) { m_uiType = rDocPage.m_uiType; m_bDirty = rDocPage.m_bDirty; m_strPath = rDocPage.m_strPath; m_strCreditURL = rDocPage.m_strCreditURL; m_strCredit = rDocPage.m_strCredit; m_strComment = rDocPage.m_strComment; m_rectSize = rDocPage.m_rectSize; m_bInflate = rDocPage.m_bInflate; m_rectInflate = rDocPage.m_rectInflate; m_hEMF = rDocPage.m_hEMF; // beware, or make copy //m_pPgComment = rDocPage.m_pPgComment; // No! Or make full copy //m_pPgCredit = rDocPage.m_pPgCredit; // No! Or make full copy } // void SCEMFDocPage::SCReset() { m_strPath.Empty(); m_strCreditURL.Empty(); m_strCredit.Empty(); m_strComment.Empty(); if (m_hEMF) { ::DeleteEnhMetaFile(m_hEMF); m_hEMF = NULL; } m_bDirty = FALSE; m_uiType = (SC_FSTATE_DELAYED|SC_FTYPE_UKN); m_rectSize.SetRectEmpty(); m_bInflate = FALSE; m_rectInflate.SetRectEmpty(); } HENHMETAFILE SCEMFDocPage::SCDetachEMF() { HENHMETAFILE hEMF = m_hEMF; m_hEMF = NULL; return hEMF; } void SCEMFDocPage::SCSetFilePath(LPCTSTR lpszPath, BOOL bKeepImage/*=TRUE*/) { ASSERT(lpszPath); m_strPath = lpszPath; if (!bKeepImage && m_hEMF) { ::DeleteEnhMetaFile(m_hEMF); m_hEMF = NULL; m_uiType = (SC_FSTATE_DELAYED|SC_FTYPE_UKN); } } void SCEMFDocPage::SCRecomputeElemsRect() { if (m_hEMF) { fnSCPlayEnhMetaFile fnPlayEMF = (SCIsGDIpEMFType(m_uiType))? SCGdipPlayMetafile :NULL; SCGetEMFElemsRect(m_hEMF, m_rectSize, fnPlayEMF); } } void SCEMFDocPage::SCGetPageBlackBox(CRect& rcElems) const { SCGetElemsRect(rcElems); if (m_pPgComment) rcElems.InflateRect(0, m_pPgComment->SCGetSize().cy, 0, 0); if (m_pPgCredit) rcElems.InflateRect(0, 0, 0, m_pPgCredit->SCGetSize().cy); } void SCEMFDocPage::SCAttachEMF(HENHMETAFILE hEMF, LPCTSTR lpszPath, UINT uiType) { ASSERT(hEMF); ASSERT(lpszPath); ASSERT(0==(uiType & ~SC_FTYPE_MASK)); if (m_hEMF) ::DeleteEnhMetaFile(m_hEMF); m_hEMF = hEMF; m_strPath = lpszPath; m_uiType = uiType; SCRecomputeElemsRect(); } HENHMETAFILE SCEMFDocPage::SCGetPageEMF() { if (!m_hEMF) {// load page switch (m_uiType & SC_FSTATE_MASK) { case SC_FSTATE_CLEARED: break; case SC_FSTATE_DELAYED: ASSERT(!m_strPath.IsEmpty()); m_uiType = SCEMFDoc::SCGetFileType(m_strPath); if (SC_FSTATE_NOTFOUND==(m_uiType & SC_FSTATE_MASK)) {// message already displayed } else if (SC_FTYPE_UKN==(m_uiType & SC_FTYPE_MASK)) { CString strMsg; strMsg.Format(SC_EMFLIB_FMTERR_FILETYPE, m_strPath); AfxMessageBox(strMsg); } else break; // error m_uiType= (m_uiType & ~SC_FSTATE_MASK)|SC_FSTATE_ERROR; return NULL; // TODO: return an error EMF instead case SC_FSTATE_DOWNLOADING: // not supported in this version // debug SC_LOGERROR(_T("Download not supported in this vesion")); return NULL; case SC_FSTATE_ERROR: return NULL; // TODO: return an error EMF instead } ASSERT(!m_strPath.IsEmpty()); switch (m_uiType & SC_FTYPE_MASK) { case SC_FTYPE_EMF: m_hEMF = ::GetEnhMetaFile(m_strPath); { ASSERT(m_hEMF); switch (SCGdipGetEMFType(m_hEMF)) { case EmfTypeEmfOnly: m_uiType = SC_FILETYPE_EMFONLY; //TODO: //SCPreFilterEMF(m_hEMF); break; case EmfTypeEmfPlusOnly: m_uiType = SC_FILETYPE_EMFPLUS; break ; case EmfTypeEmfPlusDual: m_uiType = SC_FILETYPE_EMFDUAL; break; } } break; case SC_FTYPE_WMF: m_hEMF = SCConvertWMFtoEMF(m_strPath); //ASSERT(NULL==m_hEMF || SCGdipGetEMFType(m_hEMF)==EmfTypeEmfOnly); // Windows XP was caught (wasting resources) storing private information in WMF. // Then SetWinMetaFileBits returned a dual EMF. break; case SC_FTYPE_EMZ: case SC_FTYPE_WMZ: { CMemFile MemFile; if (SCUnzipGZFile(m_strPath, MemFile)) { DWORD dwLen = MemFile.GetLength(); LPBYTE pBytes = MemFile.Detach(); m_hEMF = ((m_uiType & SC_FTYPE_MASK)==SC_FTYPE_EMZ)? ::SetEnhMetaFileBits(dwLen, pBytes) : SCConvertWMFtoEMF(dwLen, pBytes); delete [] pBytes; } ASSERT(m_hEMF); } break; case SC_FTYPE_IMG: m_hEMF = SCConvertImagetoEMF(m_strPath); ASSERT(NULL==m_hEMF || SCGdipGetEMFType(m_hEMF)==EmfTypeEmfOnly); break; default: // debug SC_LOGERROR1(_T("Page type error:%d"), m_uiType); return NULL; } SCRecomputeElemsRect(); } return m_hEMF; } HENHMETAFILE SCEMFDocPage::SCUnlockEMF() { if (!m_hEMF) return NULL; // Do it only if GetEnhMetaFile was called if (SC_FTYPE_EMF==(m_uiType & SC_FTYPE_MASK)) { HENHMETAFILE hEmfCopy = CopyEnhMetaFile(m_hEMF, NULL); DeleteEnhMetaFile(m_hEMF); m_hEMF = hEmfCopy; } return m_hEMF; } void SCEMFDocPage::SCComputePageInfo(BOOL bReverseVideo, CRect& rectMargins) { SMC_SAFEDELETE(m_pPgComment); SMC_SAFEDELETE(m_pPgCredit); // check comments/credit CString strCredit = m_strCredit; if (strCredit.IsEmpty()) strCredit = m_pParentDoc->SCGetCredit(); if (m_strComment.IsEmpty()) { if (strCredit.IsEmpty()) return; m_pPgCredit = new SCAlphaBand; } else { m_pPgComment = new SCAlphaBand; if (!strCredit.IsEmpty()) m_pPgCredit = new SCAlphaBand; } // compute unrotated page's black box CRect rcElemsRect; SCGetBasicElemsRect(rcElemsRect); rcElemsRect.InflateRect(rectMargins.left, rectMargins.top, rectMargins.right, rectMargins.bottom); CSize PgSize; PgSize.cx = rcElemsRect.Width(); PgSize.cy = rcElemsRect.Height(); int iCmtCx = 0; int iCmtCy = 0; int iCrdCy = 0; if (m_pPgComment) { m_pPgComment->SCSetFont(SC_DFLT_CMT_FACE, SC_DFLT_CMT_FAMILY, SC_DFLT_CMT_SIZE, SC_DFLT_CMT_STYLE|SC_BAND_SINGLELINE); m_pPgComment->SCSetLimits(CSize(PgSize.cx, SC_DFLT_CMT_HEIGHT), CSize(PgSize.cx, SC_DFLT_CMT_HEIGHT*3)); m_pPgComment->SCSetText(m_strComment); iCmtCx = m_pPgComment->SCComputeSize(FALSE, FALSE); iCmtCy = max(m_pPgComment->SCGetSize().cy, SC_DFLT_CMT_HEIGHT); } if (m_pPgCredit) { m_pPgCredit->SCSetFont(SC_DFLT_CRD_FACE, SC_DFLT_CRD_FAMILY, SC_DFLT_CRD_SIZE, SC_DFLT_CRD_STYLE|SC_BAND_SINGLELINE); m_pPgCredit->SCSetLimits(CSize(PgSize.cx, SC_DFLT_CRD_HEIGHT), CSize(PgSize.cx, SC_DFLT_CRD_HEIGHT*3)); m_pPgCredit->SCSetText(strCredit); iCmtCx = max(m_pPgCredit->SCComputeSize(FALSE, FALSE), iCmtCx); iCrdCy = max(m_pPgCredit->SCGetSize().cy, SC_DFLT_CRD_HEIGHT); } if (iCmtCx>PgSize.cx) { int iDltx = (iCmtCx - PgSize.cx)/2; SCInflateElemsRect(iDltx, 0, iDltx, 0); if (m_pPgComment) m_pPgComment->SCAdjustSize(iCmtCx, iCmtCy); if (m_pPgCredit) m_pPgCredit->SCAdjustSize(iCmtCx, iCrdCy); } else { if (m_pPgComment) m_pPgComment->SCAdjustSize(PgSize.cx, iCmtCy); if (m_pPgCredit) m_pPgCredit->SCAdjustSize(PgSize.cx, iCrdCy); } SCUpdatePageInfoColors(bReverseVideo); } void SCEMFDocPage::SCUpdatePageInfoColors(BOOL bReverseVideo) { // TODO: use external settings COLORREF crBkColor = RGB(0, 0, 0); COLORREF crTxtColor = (bReverseVideo)? RGB(0, 0, 0) : RGB(255, 255, 255); if (m_pPgComment) m_pPgComment->SCSetColors(crBkColor, 128, crTxtColor); if (m_pPgCredit) m_pPgCredit->SCSetColors(crBkColor, 128, crTxtColor); } void SCEMFDocPage::SCDisplayPageComments(HDC hDC, float fScale, int xDest, int yDest, int iWdt, int iHgt) { CRect rect(xDest, yDest, xDest + iWdt, yDest + iHgt); if (m_pPgComment) m_pPgComment->SCDraw(hDC, rect, TRUE, FALSE, fScale); if (m_pPgCredit) m_pPgCredit->SCDraw(hDC, rect, FALSE, TRUE, fScale); } void SCEMFDocPage::SCDisplayPageComments(HDC hDC, float fScale, int xDest, int yDest, int iWdt, int iHgt, HDC hAttribDC) { CRect rect(xDest, yDest, xDest + iWdt, yDest + iHgt); if (m_pPgComment) m_pPgComment->SCDrawMeta(hDC, rect, TRUE, FALSE, fScale, hAttribDC); if (m_pPgCredit) m_pPgCredit->SCDrawMeta(hDC, rect, FALSE, TRUE, fScale, hAttribDC); } void SCEMFDocPage::SCDisplayPageComments(void* pGraphics, float fScale, int xDest, int yDest, int iWdt, int iHgt) { CRect rect(xDest, yDest, xDest + iWdt, yDest + iHgt); if (m_pPgComment) m_pPgComment->SCDraw((Gdiplus::Graphics*)pGraphics, rect, TRUE, FALSE, fScale); if (m_pPgCredit) m_pPgCredit->SCDraw((Gdiplus::Graphics*)pGraphics, rect, FALSE, TRUE, fScale); }